package br.com.beans;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

import br.com.dao.AgendaConsultaDAO;
import br.com.dao.ConvenioDAO;
import br.com.dao.EspecialidadeDAO;
import br.com.dao.ItemSaudeDAO;
import br.com.dao.MedicoDAO;
import br.com.dao.PacienteDAO;

/** Classe que representa um agendamento de consulta  */
@Entity
@Table(name="tb_agenda")
public class AgendaConsulta {

	/** Id do agendamento */
	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	@Column(nullable=false)
	private int id;
	
	/** Paciente */
	@ManyToOne
    @JoinColumn(name="idPaciente",nullable=false)
	private Paciente paciente = new Paciente();

	/** Convenio */
	@ManyToOne
    @JoinColumn(name="codigoConvenio",nullable=false)
	private Convenio convenio = new Convenio();

	/** Medico */
	@ManyToOne
    @JoinColumn(name="unameMedico",nullable=false)
	private Medico medico = new Medico();

	/** Especialidade marcada no agendamento */
	@ManyToOne
    @JoinColumn(name="codigoEspecialidade",nullable=false)
	private Especialidade especialidade = new Especialidade();
	
	/** Item de saude (tipo CONSULTA) */
	@ManyToOne
    @JoinColumn(name="codigoItemSaude",nullable=false)
	private ItemSaude itemSaude = new ItemSaude();

	/** Data/Hora do agendamento da consulta */
	@Temporal(value=TemporalType.TIMESTAMP)
	@Column(nullable=false)
	private Date dataHora;
	
	/** Construtor padrao */
	public AgendaConsulta() {}

	/** Construtor de copia */
	public AgendaConsulta(AgendaConsulta agenda) {
		copiar(agenda);
	}

	/** Limpa todos atributos. */
	public void limpar() {
		setId(0);
		setConvenio(new Convenio());
		setEspecialidade(new Especialidade());
		setMedico(new Medico());
		setPaciente(new Paciente());
		setItemSaude(new ItemSaude());
		setDataHora(null);
	}
	
	/** Copia atributos de outro objeto.
	 *  @param obj Objeto a ser copiado */
	public void copiar(AgendaConsulta obj) {
		if (obj != null) {
			//id            = obj.id;
			paciente      = new Paciente(obj.paciente);
			convenio      = new Convenio(obj.convenio);
			medico        = new Medico(obj.medico);
			especialidade = new Especialidade(obj.especialidade);
			itemSaude     = new ItemSaude(obj.itemSaude);
			dataHora      = obj.dataHora;
		} else {
			limpar();
		}
	}
	
	/** Cadastra um item de agendamento. */
	public void cadastrar() {
		AgendaConsultaDAO agendaConsultaDAO = new AgendaConsultaDAO();
		ConvenioDAO       convenioDAO       = new ConvenioDAO();
		EspecialidadeDAO  especialidadeDAO  = new EspecialidadeDAO();
		PacienteDAO       pacienteDAO       = new PacienteDAO();
		MedicoDAO         medicoDAO         = new MedicoDAO();
		ItemSaudeDAO      itemSaudeDAO      = new ItemSaudeDAO();
		FacesMessage facesMessage = null;

		Convenio convenioObj = convenioDAO.localizar(getConvenio().getDescricao());
		if (convenioObj != null) setConvenio(convenioObj);

		Especialidade especialidadeObj = especialidadeDAO.localizar(getEspecialidade().getDescricao());
		if (especialidadeObj != null) setEspecialidade(especialidadeObj);
		
		Paciente pacienteObj = pacienteDAO.localizar(getPaciente().getNome());
		if (pacienteObj != null) setPaciente(pacienteObj);
		
		Medico medicoObj = medicoDAO.localizarPorNome(getMedico().getUsuario().getNome());
		if (medicoObj != null) setMedico(medicoObj);
		
		List<ItemSaude> listItemSaude = itemSaudeDAO.listar(ItemSaude.Tipo.CONSULTA);
		if (listItemSaude != null && listItemSaude.size() > 0) {
			ItemSaude itemSaudeObj = listItemSaude.get(0);
			if (itemSaudeObj != null) setItemSaude(itemSaudeObj);
		}
		
		if (agendaConsultaDAO.inserir(this)) {
			facesMessage = new FacesMessage("Consulta agendada com sucesso.",null);  
			limpar();
		} else {
			facesMessage = new FacesMessage("Erro ao agendar consulta.",null);  
		}
		
		FacesContext.getCurrentInstance().addMessage(null,facesMessage);  
	}

	/** Remove um item de agendamento. */
	public void remover() {
		AgendaConsultaDAO agendaConsultaDAO = new AgendaConsultaDAO();
		FacesMessage facesMessage = null;
		
		if (agendaConsultaDAO.excluir(getId())) {
			facesMessage = new FacesMessage("Agendamento cancelado com sucesso.",null);  
		} else {
			facesMessage = new FacesMessage("Erro ao cancelar agendamento.",null);  
		}
		
		limpar();
		FacesContext.getCurrentInstance().addMessage(null,facesMessage);  
	}
	
	/** Retorna uma lista de agendamentos, de acordo com o medico.
	 * @return Lista de items de agendamento. */
	public List<AgendaConsulta> getListaPorMedico() {
		AgendaConsultaDAO agendaConsultaDAO = new AgendaConsultaDAO();
		MedicoDAO medicoDAO = new MedicoDAO();
		
		Medico medicoObj = medicoDAO.localizarPorNome(getMedico().getUsuario().getNome());
		if (medicoObj != null) {
			return agendaConsultaDAO.listarPorMedico(medicoObj);
		} else {
			return agendaConsultaDAO.listar();
		}
	}
	
	/** Retorna uma lista de agendamentos, de acordo com o paciente.
	 * @return Lista de items de agendamento. */
	public List<AgendaConsulta> getListaPorPaciente() {
		AgendaConsultaDAO agendaConsultaDAO = new AgendaConsultaDAO();
		PacienteDAO pacienteDAO = new PacienteDAO();

		List<AgendaConsulta> resultado = new ArrayList<AgendaConsulta>();
		
		Paciente pacienteObj = pacienteDAO.localizar(getPaciente().getNome());
		if (pacienteObj != null) {
			resultado.addAll(agendaConsultaDAO.listarPorPaciente(pacienteObj));
		}
		return resultado;
	}
	
	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public Paciente getPaciente() {
		return paciente;
	}

	public void setPaciente(Paciente paciente) {
		this.paciente = paciente;
	}

	public Convenio getConvenio() {
		return convenio;
	}

	public void setConvenio(Convenio convenio) {
		this.convenio = convenio;
	}

	public Medico getMedico() {
		return medico;
	}

	public void setMedico(Medico medico) {
		this.medico = medico;
	}

	public Especialidade getEspecialidade() {
		return especialidade;
	}

	public void setEspecialidade(Especialidade especialidade) {
		this.especialidade = especialidade;
	}

	public Date getDataHora() {
		return dataHora;
	}

	public void setDataHora(Date dataHora) {
		this.dataHora = dataHora;
	}

	public void setItemSaude(ItemSaude itemSaude) {
		this.itemSaude = itemSaude;
	}

	public ItemSaude getItemSaude() {
		return itemSaude;
	}

}
